<?php

namespace Managers;

class Roles extends BaseManager
{
    const DEFAULT_ROLE = 'guest';

    protected $__table = '\Catalog\Roles';
    

    public function add(array $params)
    {
        $privileges = $params['privileges'];

        $role = new \Catalog\Role();
        $role->setName($params['name']);
        $role->setDescription($params['description']);
        $role->setDeletable(true);
        $role->setParent($this->_em->getRepository($this->__table)->findOneBy(array('name' => 'guest')));
        foreach ($privileges as $privilege) {
            $entity = $this->_em->getReference('\Catalog\Privileges', $privilege);
            $role->addPrivilege($entity);
        }

        $this->_em->persist($role);
        $this->_em->flush();

        return $role;
    }

    public function update(array $params)
    {
        $privileges = $params['privileges'];
       
        $role = $this->_em->find($this->__table, $params['id']);
        if ($role) {
            $role->setName($params['name']);
            $role->setDescription($params['description']);
            $role->clearPrivileges();
            foreach ($privileges as $privilege) {
                $entity = $this->_em->getReference('\Catalog\Privileges', $privilege);
                $role->addPrivilege($entity);
            }

            $this->_em->persist($role);
            $this->_em->flush();
        }

        return $role;
    }

    public function getList($parent = null)
    {
        $qb = $this->_em->createQueryBuilder()
                ->select('r')
                ->from($this->__table, 'r');

        $res = $qb->getQuery()
                ->getArrayResult();

        return $res;
    }

    public function getPrivilegesByName($name = self::DEFAULT_ROLE)
    {
        $role = $this->_em->createQueryBuilder()
                ->select('r', 'p', 'par')
                ->from($this->__table, 'r')
                ->join('r.privilege', 'p')
                ->leftJoin('r.parent', 'par')
                ->where('r.name = :name')
                ->setParameter('name', $name)
                ->getQuery()
                ->getArrayResult();

        if (count($role)) {
            $privileges = $role[0]['privilege'];
            if ($role[0]['parent']) {
                $parentPrivileges = $this->getPrivilegesByRole($role[0]['parent']['id']);
                if ($parentPrivileges) {
                    $privileges = array_merge($privileges, $parentPrivileges);
                }
            }

            return $privileges;
        }

        return false;
    }

    public function getPrivilegesByRole($id)
    {
        $role = $this->_em->createQueryBuilder()
                ->select('r', 'p', 'par')
                ->from($this->__table, 'r')
                ->join('r.privilege', 'p')
                ->leftJoin('r.parent', 'par')
                ->where('r.id = :id')
                ->setParameter('id', $id)
                ->getQuery()
                ->getArrayResult();

        if (count($role)) {
            $privileges = $role[0]['privileges'];
            if ($role[0]['parent']) {
                $parentPrivileges = $this->getPrivilegesByRole($role[0]['parent']['id']);
                if ($parentPrivileges) {
                    $privileges = array_merge($privileges, $parentPrivileges);
                }
            }

            return $privileges;
        }

        return false;
    }

    public function getById($id)
    {

        $res = $this->_em->createQueryBuilder()
                ->select('r', 'p', 'par')
                ->from($this->__table, 'r')
                ->leftJoin('r.privilege', 'p')
                ->leftJoin('r.parent', 'par')
                ->where('r.id = :id')
                ->setParameter('id', $id)
                ->getQuery()
                ->getArrayResult();

        return count($res) ? $res[0] : FALSE;
    }

    public function getTreeList($parent = null)
    {
        $cacheName = 'roles_tree_' . $parent;
        $res = $this->_getCacheManager()->load($cacheName);

        if (!$res) {

            $qb = $this->_em->createQueryBuilder()
                    ->select('r')
                    ->from($this->__table, 'r');
            if ($parent) {
                $qb = $qb->where('r.parent = :parent')
                        ->setParameter('parent', $parent);
            } else {
                $qb = $qb->where('r.parent is null');
            }

            $res = $qb->getQuery()
                    ->getArrayResult();

            foreach ($res as $i => $item) {
                $res[$i]['children'] = $this->getTreeList($item['id']);
            }

            $this->_getCacheManager()->save($res, $cacheName);
        }

        return $res;
    }

    public function getFullList()
    {
        $cacheName = 'privileges_fullList';
        $res = $this->_getCacheManager()->load($cacheName);
        
        if (!$res) {
            $res = $this->_em->createQueryBuilder()
                    ->select('partial r.{id,name}', 'partial p.{id, name}', 'partial res.{id,name}')
                    ->from($this->__table, 'r')
                    ->join('r.privilege', 'p')
                    ->join('p.resource', 'res')
                    ->getQuery()
                    ->getArrayResult();
            $this->_getCacheManager()->save($res, $cacheName);
        }

        return $res;
    }

}
